#include <gtest/gtest.h>
#include <string_view>
#include "utf_check.hpp"
using namespace Utf;
namespace Utf{
    int getByteLength(unsigned char c);
    bool isContinuationByte(unsigned char c);
    bool isCodePointValid(uint32_t code_point);
    bool isShortestEncoding(uint32_t code_point, int bytes);
    bool isUTF8(const std::string_view& str);
}
// 测试 getByteLength 函数
TEST(UtfTest, GetByteLengthTest) {
    EXPECT_EQ(Utf::getByteLength(0x41), 1); 
    EXPECT_EQ(Utf::getByteLength(0xC2), 2); 
    EXPECT_EQ(Utf::getByteLength(0xE0), 3); 
    EXPECT_EQ(Utf::getByteLength(0xF0), 4); 
    EXPECT_EQ(Utf::getByteLength(0x80), 0); 
}

// 测试 isContinuationByte 函数
TEST(UtfTest, IsContinuationByteTest) {
    EXPECT_TRUE(Utf::isContinuationByte(0x80));
    EXPECT_FALSE(Utf::isContinuationByte(0xC0));
}

// 测试 isCodePointValid 函数
TEST(UtfTest, IsCodePointValidTest) {
    EXPECT_TRUE(Utf::isCodePointValid(0x41));
    EXPECT_FALSE(Utf::isCodePointValid(0xD800));
    EXPECT_FALSE(Utf::isCodePointValid(0x110000));
    EXPECT_FALSE(Utf::isCodePointValid(0xFFFE));
}

// 测试 isShortestEncoding 函数
TEST(UtfTest, IsShortestEncodingTest) {
    EXPECT_TRUE(Utf::isShortestEncoding(0x41, 1));
    EXPECT_TRUE(Utf::isShortestEncoding(0x80, 2));
    EXPECT_TRUE(Utf::isShortestEncoding(0x800, 3));
    EXPECT_TRUE(Utf::isShortestEncoding(0x10000, 4));
    EXPECT_FALSE(Utf::isShortestEncoding(0x41, 2));
    EXPECT_FALSE(Utf::isShortestEncoding(0x41, 0));
}

// 测试 isUTF8 函数
TEST(UtfTest, IsUTF8Test) {
    EXPECT_TRUE(Utf::isUTF8("Hello, world!"));
    EXPECT_TRUE(Utf::isUTF8("你好，世界"));
    EXPECT_TRUE(Utf::isUTF8("😀👍"));
    EXPECT_FALSE(Utf::isUTF8("\x80"));  //单字节无效
    EXPECT_FALSE(Utf::isUTF8("\xC2"));  //后续字节无效
    EXPECT_FALSE(Utf::isUTF8("\xC2\xFF")); //后续字节无效
    EXPECT_FALSE(Utf::isUTF8("\xC0\xAF")); //首字节无效
    EXPECT_FALSE(Utf::isUTF8("\xED\xA0\x80")); //虽然字节序列格式正确，但对应的码点无效   0xD800，代理对
    EXPECT_FALSE(Utf::isUTF8("\xF4\x90\x80\x80"));  //U+410000超出上线
    EXPECT_TRUE(Utf::isUTF8(""));
    EXPECT_TRUE(Utf::isUTF8("\x7F"));
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
